// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once
#include "../Utils/PlatTypeUtil.h"

/**
 * Used to declare an untyped array of data with compile-time alignment.
 * It needs to use template specialization as the MS_ALIGN and GCC_ALIGN macros require literal parameters.
 */
template<int32 size, uint32 alignment>
struct TAlignedBytes; // this intentionally won't compile, we don't support the requested alignment

/** Unaligned storage. */
template<int32 size>
struct TAlignedBytes<size, 1>
{
	uint8* pad[size];
};



/** A macro that implements TAlignedBytes for a specific alignment. */
#define IMPLEMENT_ALIGNED_STORAGE(alignment) \
	template<int32 size>        \
	struct TAlignedBytes<size, alignment> \
	{ \
		struct __declspec(align(alignment)) TPadding \
		{ \
			uint8* mPad[size]; \
		}; \
		TPadding mPadding; \
	};


// Implement TAlignedBytes for these alignments.
IMPLEMENT_ALIGNED_STORAGE(16);
IMPLEMENT_ALIGNED_STORAGE(8);
IMPLEMENT_ALIGNED_STORAGE(4);
IMPLEMENT_ALIGNED_STORAGE(2);

#undef IMPLEMENT_ALIGNED_STORAGE

/** An untyped array of data with compile-time alignment and size derived from another type. */
template<typename ElementType>
struct TTypeCompatibleBytes :
	public TAlignedBytes<
	sizeof(ElementType),
	alignof(ElementType)
	>
{
	ElementType* GetTypedPtr() { return (ElementType*)this; }
	const ElementType* GetTypedPtr() const { return (const ElementType*)this; }
};
